/**
 * 
 */
package piece;

import core.AnnulationException;
import core.Couleur;
import core.DeplacementException;
import core.PlacementException;
import echiquier.Case;
import echiquier.Jeu;

/**
 * Classe pièce représentant les pièces d'échecs
 * @author julien
 *
 */
public abstract class Piece {
	/**
	 * Attributs
	 */
	private Case casePiece;
	private PieceType type;
	private Jeu jeu;
	private boolean elimine;
	
	/**
	 * Constructeurs
	 */
	public Piece(Case casePiece, Jeu jeu, PieceType type) throws PlacementException {
		super();
		casePiece.setPiece(this);
		this.casePiece = casePiece;
		this.jeu = jeu;
		this.type = type;
		this.elimine = false;
	}
	
	/**
	 * ATTENTION : Ce constructeur est utilisé par l'IHM dans la fenetre de promotion d'un pion, et ne DOIT PAS ETRE UTILISE AILLEURS. Il construit une pièce sans aucun lien avec un jeu ou échiquier.
	 * @param type Type de la pièce.
	 */
	public Piece(PieceType type){
		super();
		this.type = type;
	}
	
	/**
	 * Accesseur de l'attribut elimine
	 * @return
	 */
	public boolean estElimine() {
		return elimine;
	}
	
	/**
	 * Accesseur du jeu de la pièce
	 * @return
	 */
	protected Jeu getJeu() {
		return jeu;
	}
	
	/**
	 * Accesseur de la couleur du jeu de la pièce
	 * @return
	 */
	public Couleur getCouleur() {
		return jeu.getCouleur();
	}
	
	/**
	 * Accesseur du type de la pièce
	 * @return
	 */
	public PieceType getType() {
		return type;
	}
	
	/**
	 * Accesseur de la case de la pièce
	 * @return
	 */
	public Case getCase() {
		return this.casePiece;
	}
	
	/**
	 * Mutateur pour elimine une piece
	 */
	public void elimine() {
		elimine = true;
		casePiece.departPiece();
		casePiece = null;
	}

	/**
	 * Mutateur pour la case
	 * @param casePiece
	 */
	protected void setCase(Case casePiece) {
		this.casePiece = casePiece;
	}

	/**
	 * Méthode de déplacement d'une pièce à la case donnée, si la case donnée est nulle ou si la case est occupée par une unité alliée, elle renvoie une exception
	 * @param caseDest				case de destination
	 * @throws PlacementException	au cas où la case 
	 * @throws DeplacementException 
	 * @throws PriseException
	 */
	public Piece deplace(Case caseDest) throws DeplacementException {
		Piece pieceRes = null;
		//si la case n'est pas nulle
		if (caseDest != null || this.estElimine()) {
			
			//si il y a une piece amie sur la case
			if (!caseDest.isFree() && caseDest.getPiece().getCouleur() == this.getCouleur()) {
				throw new DeplacementException();
			//si il y a une pièce ennemie sur la case
			} else if (!caseDest.isFree() && caseDest.getPiece().getCouleur() != this.getCouleur()) {
				pieceRes = caseDest.getPiece();
				//On informe la pièce prise qu'elle est éliminée
				caseDest.getPiece().elimine();
			}
			
			if (casePiece != null) {
				//on informe la case courrante que la piece se déplace
				this.casePiece.departPiece();
			}
			//on change la case courrante
			this.casePiece = caseDest;
			//on informe la case courrante de l'arrivée de la pièce
			try {
				casePiece.setPiece(this);
			} catch (PlacementException e) {
				// TODO Auto-generated catch block
				System.out.println("Erreur d'affectation de la pièce pour la case donnée");
				throw new DeplacementException();
			}
			
		//si la case est nulle, on renvoie une exception
		} else {
			throw new DeplacementException();
		}
		return pieceRes;
	}
	
	/**
	 * Annulation d'un déplacement vers la caseSource donnée
	 * @param caseSource
	 * @throws AnnulationException
	 */
	public void annuleDeplacement(Case caseSource) throws AnnulationException {
		if (caseSource != null && caseSource.isFree()) {
			this.casePiece.departPiece();
			this.setCase(caseSource);
			try {
				caseSource.setPiece(this);
			} catch (PlacementException e) {
				throw new AnnulationException();
			}
		} else {
			throw new AnnulationException();
		}
	}

	/**
	 * Annulation d'une prise à la case donnée
	 * @param caseDestination
	 * @throws AnnulationException
	 */
	public void annulePrise(Case caseDestination) throws AnnulationException {
		if (caseDestination != null && caseDestination.isFree()) {
			this.elimine = false;
			this.casePiece = caseDestination;
			try {
				casePiece.setPiece(this);
			} catch (PlacementException e) {
				throw new AnnulationException();
			}
		} else {
			throw new AnnulationException();
		}
	}
	
	/**
	 * Conversion en chaine pour affichage
	 */
	public String toString() {
		if (elimine)
			return type + " " + this.jeu.getCouleur() + " eliminé";
		else
			return type + " " + this.jeu.getCouleur() + " " + casePiece;
	}

	/**
	 * destructeur
	 */
	public void finalize() throws Throwable {
		super.finalize();
	}
}
